/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = ora_marshaller.c                                   */
/*  NOTE      =                                                    */
/*  DATE      = 2015/01/14 by songbb                               */
/*******************************************************************/

#include <stdio.h>

#include "frcomm.h"

#include "conntrack.h"

#include "../../ora_core.h"
#include "../../comm/ora_util.h"
#include "../ora_mar_engine.h"
#include "ora_marshaller.h"

/*******************************************************************************
*  FUNC     :  解析basic方式的数据格式
*  ARGS     :  *p_st_conn                           (ct信息)
*           :  *p_st_sess                           (Oracle私有的session)
*           :  *p_st_ora_packet                     (Oracle数据包)
*           :  *p_st_metadata                       (meta信息)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int ora_marshaller_basic_unmarshal_one_row(Conntrack *p_st_conn
                                        , L7session_ora *p_st_sess
                                        , L7_ora_packet *p_st_ora_packet
                                        , Sql_metadata_info *p_st_metadata)
{
    long long ll_tmp = 0LL;
    int i_loop = 0;

    if (p_st_metadata->i_isuseless == FR_YES || p_st_metadata->i_isnullbydescribe == FR_YES)
        goto success;

    if (p_st_sess->i_use_special_field == FR_YES && p_st_metadata->s_ora_oacflg == 0x43)
    {
        ORA_PRINT_CRIT("special unmarshal for s_ora_oacflg == 0x43\n");
        if (ora_mar_unmarshalUB4(p_st_sess, p_st_ora_packet, &ll_tmp) != FR_SUCC)
            goto error;
        if (ll_tmp > 0LL)
        {
            for (i_loop = 0; i_loop < ll_tmp; i_loop++)
            {
                if (ora_mar_skipCLR(p_st_sess, p_st_ora_packet) != FR_SUCC)
                    goto error;
                if (ora_mar_skip(p_st_ora_packet, 2) != FR_SUCC)
                    goto error;
            }
        }
    }
    else
    {
        if (ora_mar_skipCLR(p_st_sess, p_st_ora_packet) != FR_SUCC)
            goto error;
    }

success:
    return FR_SUCC;
error:
    return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  解析stream方式的数据格式
*  ARGS     :  *p_st_sess                           (Oracle私有的session)
*           :  *p_st_ora_packet                     (Oracle数据包)
*           :  *p_s_escape                          (escape)
*           :  *p_i_readHeaderArr                   (header)
*           :  *p_i_readAsNonStreamArr              (NonStream)
*           :  *p_i_length                          (长度)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __ora_marshaller_readStreamFromWire(L7session_ora *p_st_sess
                                            , L7_ora_packet *p_st_ora_packet
                                            , short *p_s_escape
                                            , int *p_i_readHeaderArr
                                            , int *p_i_readAsNonStreamArr
                                            , int *p_i_length)
{
    short s_tmp = 0;
    int i_tmp = 0;

    *p_i_length = -1;

    if (!*p_i_readAsNonStreamArr)
    {
        if (*p_i_readHeaderArr)
        {
            if (*p_s_escape == 254)
            {
                if (p_st_sess->i_use_special_field == FR_NO && p_st_sess->i_useCLR_big_chunks)
                {
                    if (ora_mar_unmarshalSB4(p_st_sess, p_st_ora_packet, p_i_length) != FR_SUCC)
                        goto error;
                }
                else
                {
                    if (ora_mar_unmarshalUB1(p_st_ora_packet, &s_tmp) != FR_SUCC)
                        goto error;
                    *p_i_length = s_tmp;
                }
            }
            else
            {
                if (*p_s_escape == 0)
                {
                    ORA_PRINT_EMERG("s_escape == 0.\n");
                    ORA_FRLOG_ERROR("s_escape == 0.");
                    goto error;
                }
                *p_i_readAsNonStreamArr = 1;
                *p_i_length = *p_s_escape;
            }
            *p_i_readHeaderArr = 0;
            *p_s_escape = 0;
        }
        else if (p_st_sess->i_use_special_field == FR_NO && p_st_sess->i_useCLR_big_chunks)
        {
            if (ora_mar_unmarshalSB4(p_st_sess, p_st_ora_packet, p_i_length) != FR_SUCC)
                goto error;
        }
        else
        {
            if (ora_mar_unmarshalUB1(p_st_ora_packet, &s_tmp) != FR_SUCC)
                goto error;
            *p_i_length = s_tmp;
        }
    }
    else
        *p_i_readAsNonStreamArr = 0;
    if (*p_i_length > 0)
    {
        if (ora_mar_check_bufflen(p_st_ora_packet, (unsigned long long) *p_i_length) != FR_SUCC)
            goto error;

        if (ora_mar_skip(p_st_ora_packet, (size_t) *p_i_length) != FR_SUCC)
            goto error;
    }
    else
        *p_i_length = -1;

    if (*p_i_length == -1)
    {
        *p_i_readHeaderArr = 1;
        if (ora_mar_unmarshalUB2(p_st_sess, p_st_ora_packet, &i_tmp) != FR_SUCC)
            goto error;
        if (ora_mar_unmarshalUB2(p_st_sess, p_st_ora_packet, &i_tmp) != FR_SUCC)
            goto error;
    }

    return FR_SUCC;
error:
    return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  stream方式的数据格式
*  ARGS     :  *p_st_conn                           (ct信息)
*           :  *p_st_sess                           (Oracle私有的session)
*           :  *p_st_ora_packet                     (Oracle数据包)
*           :  *p_st_metadata                       (meta信息)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int ora_marshaller_stream_unmarshal_one_row(Conntrack *p_st_conn
                                            , L7session_ora *p_st_sess
                                            , L7_ora_packet *p_st_ora_packet
                                            , Sql_metadata_info *p_st_metadata)
{
    char c_tmp = 0;
    int i_tmp = 0;
    short s_escape = 0;
    int i_ret = 0;
    int i_readHeaderArr = 1;
    int i_readAsNonStreamArr = 0;
    int i_length_total = 0;
    int i_length_block = 0;

    if (p_st_metadata->i_isuseless == FR_YES)
        goto success;

    if (ora_mar_unmarshalUB1(p_st_ora_packet, &s_escape) != FR_SUCC) // escapeSequenceArr[0]
        goto error;

    if (ora_mar_escapeSequenceNull(s_escape, &i_ret) != FR_SUCC)
        goto error;

    if (i_ret)
    {
        if (ora_mar_unmarshalSB1(p_st_sess, p_st_ora_packet, &c_tmp) != FR_SUCC)
            goto error;

        if (ora_mar_unmarshalUB2(p_st_sess, p_st_ora_packet, &i_tmp) != FR_SUCC)
            goto error;
    }
    else
    {
        while (i_length_block != -1)
        {
            if (__ora_marshaller_readStreamFromWire(p_st_sess, p_st_ora_packet, &s_escape, &i_readHeaderArr, &i_readAsNonStreamArr, &i_length_block) != FR_SUCC)
                goto error;
            if (i_length_block != -1)
                i_length_total += i_length_block;
        }
    }

success:
    return FR_SUCC;
error:
    return FR_FAIL;
}
